home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / misc / Fudgit233.lha / Source / src / plot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-14  |  7.0 KB  |  315 lines

  1. #include <signal.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6.  
  7. #ifndef NOSTDLIB_H
  8. #include <stdlib.h>
  9. #endif
  10. #ifndef NOUNISTD_H
  11. #include <unistd.h>
  12. #endif
  13.  
  14. #include "fudgit.h"
  15. #include "setshow.h"
  16. #include "macro.h"
  17. #include "head.h"
  18.  
  19. #define READ 0
  20. #define WRITE 1
  21. #ifdef NOSETPGID
  22. #define setpgid setpgrp
  23. #endif
  24.  
  25. static int Plotfd = ERRR;
  26. static FILE *Plotfp = (FILE *)NULL;
  27. static int Pid = 0;
  28. static SIGHANDLER bangplot(int);
  29. static void reapit(void);
  30.  
  31. extern int Ft_Interact;
  32. extern int Ft_Dolevel;
  33. extern int Ft_almost (char *, char *);
  34. extern int Ft_iolevel (void);
  35. #ifdef NeXT
  36. extern int putenv (const char *);
  37. extern char *strstr (const char *, const char *);
  38. #endif
  39.  
  40. int plot(int init)  /* return silently if init = 1 */
  41. {
  42.     char *cp;
  43.     int i;
  44.  
  45.     if (init && Pid) {
  46.         return(0);
  47.     }
  48.     if (Ft_Plotting[0][0] == '\0') {
  49.         if (Ft_Interact && !Ft_iolevel()) {
  50.             fprintf(stderr, "Error: pmode: Null plotting program.\n");
  51.             return(ERRR);
  52.         }
  53.         Pid = ERRR;
  54.     }
  55.     else if (!Pid) { /* No program running: start one */
  56.         int pfd[2];
  57.         struct stat buf;
  58.  
  59.         if (stat(Ft_Plotting[0], &buf) != 0) {
  60.             fprintf(stderr, "Error: %s: Invalid plotting program.\n",
  61.             Ft_Plotting[0]);
  62.             return(ERRR);
  63.         }
  64.  
  65.         if (pipe(pfd) == ERRR) {
  66.             perror("pipe");
  67.             return (ERRR);
  68.         }
  69.         Pid = fork();
  70.         if (Pid == 0) {  /* the child */
  71.             char *vec[MAXPARG];
  72.  
  73.             close(0);  /* close stdin */
  74.             close(pfd[WRITE]);
  75.             dup2(pfd[READ], 0);  /* dup pipe read to plotting program stdin */
  76.             if (pfd[READ] > 2) {
  77.                 close(pfd[READ]);
  78.             }
  79.             for (i=0; Ft_Plotting[i][0] != '\0' && i<MAXPARG;i++) {
  80.                 vec[i] = Ft_Plotting[i];
  81.             }
  82.             vec[i] = 0;
  83. #ifdef ultrix
  84.             if (setpgid(0, getpid()) == ERRR) {
  85. #else
  86.             if (setpgid(0, 0) == ERRR) {
  87. #endif
  88.                 fprintf(stderr,
  89.                 "Error: pmode: Could not set child process group to %d.\n",
  90.                 getpid());
  91.                 perror("setpgid");
  92.                 exit(1);
  93.             }
  94.             putenv("PAGER="); /* turn off gnuplot PAGER */
  95.             if (execv(vec[0], vec) == ERRR) {
  96.                 sleep(1);
  97.                 fprintf(stderr,
  98.                 "Error: pmode: %s: Program not found.\n", vec[0]);
  99.                 perror("exec");
  100.                 exit(1);
  101.             }
  102.         }
  103.         else if (Pid > 0) { /* the parent */
  104.             close(pfd[READ]);
  105.             if (Plotfd != ERRR) { /* close leftover */
  106.                 fclose(Plotfp);
  107.                 close(Plotfd);
  108.                 Plotfd = ERRR;
  109.             }
  110.             Plotfd = pfd[WRITE];
  111.             if ((Plotfp = fdopen(Plotfd, "w")) == (FILE *)NULL) {
  112.                 fprintf(stderr,
  113.                 "Error: pmode: Could not get fdopen working.\n");
  114.                 close(pfd[WRITE]);
  115.                 return(ERRR);
  116.             }
  117.         }   
  118.         else if (Pid == ERRR) {
  119.             perror("fork");
  120.             close(pfd[READ]);
  121.             close(pfd[WRITE]);
  122.             Pid = 0;
  123.             return(ERRR);
  124.         }
  125.         if (init) { /* we've done the job of init now */
  126.             return(0);
  127.         }
  128.     }
  129.     if (Ft_Interact && !Ft_iolevel())
  130.         fprintf(stderr, "\tUse `fmode' or ^D to come back...\n");
  131.  
  132.     signal(SIGINT, bangplot);
  133.     Ft_Mode = PMODE;
  134.     while (Pid) {
  135.         if ((cp = Ft_expandedline(Ft_Prompt_pm, EXPANSION, &i)) == (char *)0) {
  136.             if (i) {  /* end of file or ^D */
  137.                 signal(SIGINT, Ft_catcher);
  138.                 if (i > 0) /* in a file or macro */
  139.                     fprintf(stderr,
  140.                     "Warning: Eof or Eom occurred while still in pmode.\n");
  141.                 return(0);
  142.             }
  143.             if (Pid > 0) {
  144.                 if (write(Plotfd, "\n", 1) == ERRR) {
  145.                     reapit();
  146.                 }
  147.             }
  148.             continue;
  149.         }
  150.         if (Ft_almost(cp, "fm!ode")) {
  151.             signal(SIGINT, Ft_catcher);
  152.             return(0);
  153.         }
  154.         if (Ft_almost(cp, "pm!ode")) {
  155.             fprintf(stderr,
  156.             "Warning: pmode: Program already in plotting mode: Line ignored.\n");
  157.             continue;
  158.         }
  159.         if (Pid > 0) {
  160.             if (write(Plotfd, cp, strlen(cp)) == ERRR) {
  161.                 reapit();
  162.             }
  163.         }
  164.         else {  /* Pid == ERRR means plotting program a null string */
  165.             fprintf(stderr, "Warning: pmode: Line ignored: %s", cp);
  166.         }
  167.     }
  168.     signal(SIGINT, Ft_catcher);
  169.     plot(1);
  170.     if (Ft_Interact && !Ft_iolevel() && !Ft_Dolevel) {
  171.         fprintf(stderr,
  172.         "Warning: pmode: Dead plotting program ... restarted.\n");
  173.         return(0);
  174.     }
  175.     fprintf(stderr,
  176.     "Error: pmode: Dead plotting program ... restarted.\n");
  177.     return(ERRR);
  178. }
  179.  
  180.  
  181. int Ft_dumplot(double **dblv, int ndata)
  182. {
  183.     int i, j;
  184.     extern int Plotfd;
  185.     extern FILE *Plotfp;
  186.  
  187.     /* check if still alive */
  188.     if (Pid > 0 && write(Plotfd, " ", 1) == ERRR) {
  189.         reapit();
  190.            fprintf(stderr, 
  191.         "Warning: pmode: Dead plotting program ... restarted.\n");
  192.         plot(1);
  193.     }
  194.     else if (!Pid) {
  195.         plot(1);
  196.     }
  197.  
  198.     if (Pid > 0) {
  199.         for (i=1;i<=ndata;i++) {
  200.             fprintf(Plotfp, "%.9g", dblv[0][i]);
  201.             for (j=1;dblv[j];j++) {
  202.                 fprintf(Plotfp, "\t%.9g", dblv[j][i]);
  203.             }
  204.             fputc('\n', Plotfp);
  205.         }
  206.         fflush(Plotfp);
  207.     }
  208.     return(0);
  209. }
  210.  
  211. int Ft_killplot(void)
  212. {
  213.     if (Pid > 0) {
  214.         kill(Pid, SIGKILL);
  215.         reapit();
  216.     }
  217.     return(0);
  218. }
  219.  
  220.  /* PMODE FUNCTION */
  221. #include "command.h"
  222.  
  223. int Ft_pmode(int argc, char **argv, char *line, Command *cmp)
  224. {
  225.     /* check if still alive */
  226.     if (Pid > 0 && write(Plotfd, "\n", 1) == ERRR) {
  227.         reapit();
  228.         plot(1);
  229.         if (!Ft_Interact || Ft_iolevel() || Ft_Dolevel) {
  230.                fprintf(stderr,
  231.             "Error: pmode: Dead plotting program ... restarted.\n");
  232.             return(ERRR);
  233.         }
  234.            fprintf(stderr, 
  235.         "Warning: pmode: Dead plotting program ... restarted.\n");
  236.     }
  237.     else if (!Pid) {
  238.          plot(1);
  239.     }
  240.  
  241.     if (argc == 1) {
  242.         return(plot(0));
  243.     }
  244.     else {
  245.         char *cp;
  246.  
  247.         cp = strstr(line, argv[1]);
  248.         if (Pid > 0) {
  249.             if (write(Plotfd, cp, strlen(cp)) == ERRR) {
  250.                 reapit();
  251.                 plot(1);
  252.                 fprintf(stderr,
  253.                 "Error: pmode: Dead plotting program ... restarted.\n");
  254.                 return(ERRR);
  255.             }
  256.         }
  257.         else {
  258.             fprintf(stderr, "Warning: pmode: Line ignored: %s", cp);
  259.         }
  260.         return(0);
  261.     }
  262. }
  263.  
  264. static SIGHANDLER bangplot(int sig)
  265. {
  266.     if (Pid <= 0) {
  267.         fprintf(stderr,
  268.         "Warning: pmode: No plotting program to interrupt!\n");
  269.     }
  270.     else {
  271.         if (kill(Pid, SIGINT) != ERRR) {
  272.             reapit();
  273.             plot(1);
  274.             fprintf(stderr,
  275.             "Warning: pmode: Plotting program killed and ... restarted.\n");
  276.         }
  277.         else {
  278.             fprintf(stderr,
  279.             "Warning: pmode: Could not interrupt plotting program.\n");
  280.         }
  281.     }
  282. #ifdef RESTART_SIGHANDLER
  283.     signal(SIGINT, bangplot);
  284. #endif
  285. #ifndef VOID_SIGHANDLER
  286.     return(0);
  287. #endif
  288. }
  289.  
  290. #include <sys/types.h>
  291. #include <sys/wait.h>
  292.  
  293. static void reapit()
  294. {
  295. /* Use wait3 if waitpid() is not accessible */
  296. #ifdef NOWAITPID
  297.     union wait status;
  298.  
  299. #ifdef WAIT4
  300.     while (wait4(Pid, &status, WNOHANG, 0) > 0) {
  301. #else
  302.     while (wait3(&status, WNOHANG, 0) > 0) {
  303. #endif /* WAIT4 */
  304. #else  /* NOWAITPID */
  305.     int stat;
  306.  
  307.     while (waitpid((pid_t) Pid, &stat, WNOHANG) > 0) {
  308. #endif
  309.         ;
  310.     }
  311.     Pid = 0;
  312. }
  313.  
  314.  
  315.